package com.lpf;

import java.lang.instrument.Instrumentation;

/**
 * premain() 方法有两个重载，如下，如果两个重载同时存在，【1】将会被忽略，只执行【2】。
 * <p>
 * 确定 premain() 方法的两个重载优先级的逻辑在 sun.instrument.InstrumentationImpl 中实现（loadClassAndCallPremain方法）。
 */
// VM options：-javaagent:E:\IdeaProjects\skywalking\skywalking-learning\java-agent\target\java-agent-1.0.0.jar=key1=value1,key2=value2
// 配合 java-main 模块中的 PremainMain01 类运行
public class PremainTest01 {

    public static void premain(String agentArgs) {
        System.out.println("this is a java agent only one args");
        System.out.println("参数:" + agentArgs + "\n");
    }

    /**
     * @param agentArgs -javaagent 命令携带的参数
     * @param inst      java.lang.instrumen.Instrumentation 是 Instrumention 包中定义的一个接口，它提供了操作类定义的相关方法
     */
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("this is a java agent with two args");
        System.out.println("参数:" + agentArgs + "\n");

        // 输出如下：
        // this is a java agent with two args
        // 参数:key1=value1,key2=value2
    }

    /**
     * Instrumentation 位于 java.lang.instrument 包中，通过这个工具包，可以编写一个强大的 Java Agent 程序，用来动态替换或是修改某些类的定义。
     *
     * 简单介绍一下 Instrumentation 中的核心 API 方法：
     * - addTransformer()/removeTransformer() 方法：注册/注销一个 ClassFileTransformer 类的实例（该 Transformer 会在类加载的时候被调用，可用于修改类定义）。
     * - redefineClasses() 方法：该方法针对的是已经加载的类，它会对传入的类进行重新定义。
     * - getAllLoadedClasses()方法：返回当前 JVM 已加载的所有类。
     * - getInitiatedClasses() 方法：返回当前 JVM 已经初始化的类。
     * - getObjectSize()方法：获取参数指定的对象的大小。
     */

}
